import com.wxc.list.AbsList;

/**
 * @program: LoveDataStructures1
 * @description: 链表类
 * @author: wxc
 * @create: 2021-04-03 21:18
 **/
public class LinkList<E> extends AbsList<E> {
    private Node<E> firstNode;

    @Override
    public E get(int index) {
        return getNodeByIndex(index).element;
    }

    @Override
    public E set(int index, E element) {
        Node<E> node = getNodeByIndex(index);
        E oldElement = node.element;
        node.element = element;
        return oldElement;
    }

    @Override
    public void add(int index, E element) {
        // 处理0的情况
        if (index == 0){
            firstNode = new Node<>(element, firstNode);
        }else {
            Node<E> preNode = getNodeByIndex(index - 1);
            preNode.next = new Node<>(element, preNode.next);
        }
        size++;
    }

    @Override
    public E remove(int index) {
        E element;
        if (index == 0){
            rangeCheck(index);
            element = firstNode.element;
            firstNode = firstNode.next;
        }else {
            Node<E> preNode = getNodeByIndex(index - 1);
            element = preNode.next.element;
            preNode.next = preNode.next.next;
        }
        size--;
        return element;
    }

    @Override
    public int indexOf(E element) {
        Node<E> tempNode = firstNode;
        if (element == null){
            for (int i = 0; i < size; i++, tempNode = tempNode.next) {
                if (tempNode.element == null) return i;
            }
        }else {
            for (int i = 0; i < size; i++, tempNode = tempNode.next) {
                if (element.equals(tempNode.element)) return i;
            }
        }
        return -1;
    }

    @Override
    public void clear() {
        size = 0;
        firstNode = null;
    }


    private static class Node<E> {
        E element;
        Node<E> next;

        public Node(E element, Node<E> next) {
            this.element = element;
            this.next = next;
        }
    }

    private Node<E> getNodeByIndex(int index) {
        rangeCheck(index);

        Node<E> tempNode = firstNode;
        while (index > 0) {
            tempNode = tempNode.next;
            index--;
        }
        return tempNode;
    }

    @Override
    public String toString() {
        StringBuilder string = new StringBuilder();
        string.append("size = ").append(size).append(", [");
        Node<E> node = firstNode;
        for (int i = 0; i < size; i++) {
            if (i != 0) {
                string.append(",");
            }
            string.append(node.element);
            node = node.next;
        }
        string.append("]");
        return string.toString();
    }
}
